#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
LANG=en_US.UTF-8

clear

# 当前目录
CURRENT_DIR=$(pwd)

# 脚本目录
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )

# 脚本名称
SCRIPT_NAME=$(basename "$0")

# 当前参数数量
VAR_COUNT="$#"

# Jar包运行参数
CONFIG_JAR="-Duser.timezone=Asia/Shanghai -Xms512m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:NewRatio=1 -XX:SurvivorRatio=30 -XX:+UseParallelGC -XX:+UseParallelOldGC"

# Jar包运行日志
CONFIG_LOG_PATH=""

# 指定运行的Java
CONFIG_JAVA=""

# 是否强制停止Jar
FORCE_KILL="false"

# 主命令
MAIN_PARAM=$1

# 文件命令
FILE_PARAM=$2
  
# 手动解析命令行参数  
while [ "$#" -gt 0 ]; do  
  case "$1" in  
    --config-jar=*)  
      CONFIG_JAR="${1#*=}"
      shift  
      ;;  
    --config-log-path=*)
      CONFIG_LOG_PATH="${1#*=}"
      shift
      ;;
    --config-java=*)
      CONFIG_JAVA="${1#*=}"
      shift
      ;;
    *)
      shift  
      ;; 
  esac  
done

# 获取maven的项目名称
get_maven_project_name() {
    JAR_PATH=$1
    POM_PATHS=$(jar tf "$JAR_PATH" | grep "pom.xml")
    JAR_FILENAME=$(basename $JAR_PATH)
    which xmllint > /dev/null 2>&1
    if [ $? == 0 ]; then
        for POM_PATH in $POM_PATHS; do  
            POM_FILE=$(unzip -p "$JAR_PATH" "$POM_PATH")
            PROJECT_NAME=$(xmllint --format --xpath '/*[local-name()="project"]/*[local-name()="name"]/text()' <(echo $POM_FILE))
            PROJECT_NAME=$(echo "$PROJECT_NAME" | sed -r 's/&#x([0-9a-fA-F]{4});/\\u\1/g' | xargs -0 printf "%b")
            echo "$PROJECT_NAME"
        done 
    else
        echo '安装 xmllint 库获取Maven的项目名称'
    fi
}

# 获取maven的项目编号
get_maven_project_artifact_ids() {
    JAR_PATH=$1
    POM_PATHS=$(jar tf "$JAR_PATH" | grep "pom.xml")
    JAR_FILENAME=$(basename $JAR_PATH)
    which xmllint > /dev/null 2>&1
    if [ $? == 0 ]; then
        for POM_PATH in $POM_PATHS; do  
            POM_FILE=$(unzip -p "$JAR_PATH" "$POM_PATH")
            ARTIFACT_ID=$(xmllint --format --xpath '/*[local-name()="project"]/*[local-name()="artifactId"]/text()' <(echo $POM_FILE))
            ARTIFACT_ID=$(echo "$ARTIFACT_ID" | sed -r 's/&#x([0-9a-fA-F]{4});/\\u\1/g' | xargs -0 printf "%b")
            echo "$ARTIFACT_ID" | tr '\n' ',' | sed 's/.$//'
        done 
    else
        echo '安装 xmllint 库获取Maven的项目编号'
    fi
}

# 当前项目是否在运行
is_run() {
    CURRENT_JAR_PATH=$1
    jps -l | while read -r line; do
        JVM_ID=$(echo $line | awk '{print $1}')
        JAR_PATH=$(echo $line | awk '{print $2}')
        if [[ $JAR_PATH != */* ]]; then
            JAR_PATH="$CURRENT_DIR/$JAR_PATH"
        fi
        if [[ $JAR_PATH == $CURRENT_DIR* ]]; then
            if [ "$CURRENT_JAR_PATH" == "$JAR_PATH" ]; then
                echo "true"
            fi
        fi
    done
}

# 获取当前运行中的jvmid
get_run_jvm_id() {
    CURRENT_JAR_PATH=$1
    jps -l | while read -r line; do
        JVM_ID=$(echo $line | awk '{print $1}')
        JAR_PATH=$(echo $line | awk '{print $2}')
        if [[ $JAR_PATH != */* ]]; then
            JAR_PATH="$CURRENT_DIR/$JAR_PATH"
        fi
        if [[ $JAR_PATH == $CURRENT_DIR* ]]; then
            if [ "$CURRENT_JAR_PATH" == "$JAR_PATH" ]; then
                echo "$JVM_ID"
            fi
        fi
    done
}

# 获取当前运行中的jvm参数
get_run_jvm_param(){
    CURRENT_JAR_PATH=$1
    jps -lv | while read -r line; do
        JVM_ID=$(echo $line | awk '{print $1}')
        JAR_PATH=$(echo $line | awk '{print $2}')
        JAR_PARAM=$(echo $line | awk '{$1=$2=""; print substr($0, index($0, $3))}')
        if [[ $JAR_PATH != */* ]]; then
            JAR_PATH="$CURRENT_DIR/$JAR_PATH"
        fi
        if [[ $JAR_PATH == $CURRENT_DIR* ]]; then
            if [ "$CURRENT_JAR_PATH" == "$JAR_PATH" ]; then
                echo "$JAR_PARAM"
            fi
        fi
    done   
}

# 获取当前运行中的端口
get_run_port() {
    CURRENT_JAR_PATH=$1
    lsof -nP -iTCP -sTCP:LISTEN | grep $(get_run_jvm_id "$CURRENT_JAR_PATH") | awk '{for(i=9;i<=NF;i++) if($i ~ /:[0-9]+$/) print $i}' | cut -d: -f2
}

# 当前目录的项目状态
status() {
    echo ""
    echo "SimpleJarBoot (简单的Jar启动器)"
    PARAM_JAR_PATH="$1"
    JAR_COUNT=0
    # 遍历当前目录下的所有.jar文件  
    for CURRENT_DIR_JAR_FILE in *.jar; do
        if [ ! -e "$CURRENT_DIR_JAR_FILE" ]; then
            continue
        fi
        PROJECT_NAME=$(get_maven_project_name $CURRENT_DIR_JAR_FILE | tr '\n' ',' | sed 's/.$//')
        IS_CURRENT_RUN=$(is_run "$CURRENT_DIR/$CURRENT_DIR_JAR_FILE")
        if [[ "$PARAM_JAR_PATH" == "" ]]; then
            ((JAR_COUNT++))
            if [[ "$IS_CURRENT_RUN" == "true" ]]; then
                echo ""
                echo "状态: 运行中"
                echo "进程编号: $(get_run_jvm_id "$CURRENT_DIR/$CURRENT_DIR_JAR_FILE")"
                echo "进程参数: $(get_run_jvm_param "$CURRENT_DIR/$CURRENT_DIR_JAR_FILE")"
                echo "项目编号: $(get_maven_project_artifact_ids "$CURRENT_DIR/$CURRENT_DIR_JAR_FILE")"
                RUN_PORT=$(get_run_port "$CURRENT_DIR/$CURRENT_DIR_JAR_FILE")
                if [[ "$RUN_PORT" != "" ]]; then
                    echo "项目端口: $RUN_PORT"
                fi
                echo "项目名称: $PROJECT_NAME"
                echo "项目文件: $CURRENT_DIR_JAR_FILE"
                echo "项目: $FORCE_KILL"
            else
                echo ""
                echo "状态: 未启动"
                echo "项目编号: $(get_maven_project_artifact_ids "$CURRENT_DIR/$CURRENT_DIR_JAR_FILE")"
                echo "项目名称: $PROJECT_NAME"
                echo "项目文件: $CURRENT_DIR_JAR_FILE"
            fi
        else
            if [[ "$PARAM_JAR_PATH" == "$CURRENT_DIR_JAR_FILE" ]]; then
                ((JAR_COUNT++))
                if [[ "$IS_CURRENT_RUN" == "true" ]]; then
                    echo ""
                    echo "状态: 运行中"
                    echo "进程编号: $(get_run_jvm_id "$CURRENT_DIR/$CURRENT_DIR_JAR_FILE")"
                    echo "进程参数: $(get_run_jvm_param "$CURRENT_DIR/$CURRENT_DIR_JAR_FILE")"
                    echo "项目编号: $(get_maven_project_artifact_ids "$CURRENT_DIR/$CURRENT_DIR_JAR_FILE")"
                    RUN_PORT=$(get_run_port "$CURRENT_DIR/$CURRENT_DIR_JAR_FILE")
                    if [[ "$RUN_PORT" != "" ]]; then
                        echo "项目端口: $RUN_PORT"
                    fi
                    echo "项目名称: $PROJECT_NAME"
                    echo "项目文件: $CURRENT_DIR_JAR_FILE"
                else
                    echo ""
                    echo "状态: 未启动"
                    echo "项目编号: $(get_maven_project_artifact_ids "$CURRENT_DIR/$CURRENT_DIR_JAR_FILE")"
                    echo "项目名称: $PROJECT_NAME"
                    echo "项目文件: $CURRENT_DIR_JAR_FILE"
                fi
            fi
        fi
    done
    if [[ "$JAR_COUNT" == "0" ]]; then
        clear
        echo ""
        echo "SimpleJarBoot (简单的Jar启动器)"
        echo ""
        echo "当前目录没有找到.jar后缀的文件"
    fi
    echo ""
}

# 日志查看
log() {
    echo ""
}

# 开启
start() {
    clear
    echo ""
    echo "SimpleJarBoot (简单的Jar启动器)"
    echo ""
    PARAM_JAR_PATH="$1"
    JAR_COUNT=0
    for CURRENT_DIR_JAR_FILE in *.jar; do
        if [ ! -e "$CURRENT_DIR_JAR_FILE" ]; then
            continue
        fi
        PROJECT_NAME=$(get_maven_project_name $CURRENT_DIR_JAR_FILE | tr '\n' ',' | sed 's/.$//')
        IS_CURRENT_RUN=$(is_run "$CURRENT_DIR/$CURRENT_DIR_JAR_FILE")
        if [[ "$PARAM_JAR_PATH" != "" ]]; then
            if [[ "$PARAM_JAR_PATH" == "$CURRENT_DIR_JAR_FILE" ]]; then
                ((JAR_COUNT++))
                if [[ "$IS_CURRENT_RUN" == "true" ]]; then
                    echo "状态: 运行中"
                    echo "进程编号: $(get_run_jvm_id "$CURRENT_DIR/$CURRENT_DIR_JAR_FILE")"
                    echo "进程参数: $(get_run_jvm_param "$CURRENT_DIR/$CURRENT_DIR_JAR_FILE")"
                    echo "项目编号: $(get_maven_project_artifact_ids "$CURRENT_DIR/$CURRENT_DIR_JAR_FILE")"
                    RUN_PORT=$(get_run_port "$CURRENT_DIR/$CURRENT_DIR_JAR_FILE")
                    if [[ "$RUN_PORT" != "" ]]; then
                        echo "项目端口: $RUN_PORT"
                    fi
                    echo "项目名称: $PROJECT_NAME"
                    echo "项目文件: $CURRENT_DIR/$PARAM_JAR_PATH"
                    echo ""
                    echo " * Jar已经在运行中 * "
                    echo ""
                else
                    echo "项目编号: $(get_maven_project_artifact_ids "$CURRENT_DIR/$CURRENT_DIR_JAR_FILE")"
                    echo "项目名称: $PROJECT_NAME"
                    echo "项目文件: $CURRENT_DIR/$PARAM_JAR_PATH"
                    echo ""
                    echo " * Jar启动中"
                    FILE_NAME=${PARAM_JAR_PATH%.*}
                    DNAME="-Dname=$PARAM_JAR_PATH"
                    if [[ "$CONFIG_JAR" == *"-Dname="* ]]; then
                        DNAME=""
                    fi
                    if [[ "$CONFIG_LOG_PATH" == "" ]]; then
                        mkdir -p "$CURRENT_DIR/jar-logs"
                        CONFIG_LOG_PATH="$CURRENT_DIR/jar-logs/$FILE_NAME.log"
                    fi
                    if [[ "$CONFIG_JAVA" == "" ]]; then
                        CONFIG_JAVA="java"
                    fi
                    nohup $CONFIG_JAVA -jar $DNAME $CONFIG_JAR "$CURRENT_DIR/$PARAM_JAR_PATH" > "$CONFIG_LOG_PATH" 2>&1 &
                    echo ""
                    clear
                    echo ""
                    echo "SimpleJarBoot (简单的Jar启动器)"
                    echo ""
                    echo "状态: 运行中"
                    echo "进程编号: $(get_run_jvm_id "$CURRENT_DIR/$CURRENT_DIR_JAR_FILE")"
                    echo "进程参数: $(get_run_jvm_param "$CURRENT_DIR/$CURRENT_DIR_JAR_FILE")"
                    echo "项目编号: $(get_maven_project_artifact_ids "$CURRENT_DIR/$CURRENT_DIR_JAR_FILE")"
                    RUN_PORT=$(get_run_port "$CURRENT_DIR/$CURRENT_DIR_JAR_FILE")
                    if [[ "$RUN_PORT" != "" ]]; then
                        echo "项目端口: $RUN_PORT"
                    fi
                    echo "项目名称: $PROJECT_NAME"
                    echo "项目文件: $CURRENT_DIR/$PARAM_JAR_PATH"
                    echo "项目日志: $CONFIG_LOG_PATH"
                    echo ""
                    echo "Java版本"
                    $CONFIG_JAVA -version
                    echo ""
                    echo " * Jar启动完成 * "
                    echo ""
                fi
            fi
        fi
    done
    if [[ "$JAR_COUNT" == "0" ]]; then
        clear
        echo ""
        echo "SimpleJarBoot (简单的Jar启动器)"
        echo ""
        echo "没有找到要启动的Jar文件"
        echo ""
    fi
}

# 关闭
stop() {
    clear
    echo ""
    echo "SimpleJarBoot (简单的Jar启动器)"
    echo ""
    PARAM_JAR_PATH="$1"
    JAR_COUNT=0
    for CURRENT_DIR_JAR_FILE in *.jar; do
        if [ ! -e "$CURRENT_DIR_JAR_FILE" ]; then
            continue
        fi
        PROJECT_NAME=$(get_maven_project_name $CURRENT_DIR_JAR_FILE | tr '\n' ',' | sed 's/.$//')
        IS_CURRENT_RUN=$(is_run "$CURRENT_DIR/$CURRENT_DIR_JAR_FILE")
        if [[ "$PARAM_JAR_PATH" != "" ]]; then
            if [[ "$PARAM_JAR_PATH" == "$CURRENT_DIR_JAR_FILE" ]]; then
                ((JAR_COUNT++))
                if [[ "$IS_CURRENT_RUN" == "true" ]]; then
                    echo " * 准备停止Jar包 * "
                    echo ""
                    JVM_ID=$(get_run_jvm_id "$CURRENT_DIR/$CURRENT_DIR_JAR_FILE")
                    echo "$JVM_ID"
                    kill -15 $JVM_ID
                    WAIT_COUNT=1
                    while [[ "$IS_CURRENT_RUN" == "true" ]];do
                        clear
                        echo ""
                        echo "SimpleJarBoot (简单的Jar启动器)"
                        echo ""
                        echo "状态: 运行中"
                        echo "进程编号: $(get_run_jvm_id "$CURRENT_DIR/$CURRENT_DIR_JAR_FILE")"
                        echo "项目编号: $(get_maven_project_artifact_ids "$CURRENT_DIR/$CURRENT_DIR_JAR_FILE")"
                        RUN_PORT=$(get_run_port "$CURRENT_DIR/$CURRENT_DIR_JAR_FILE")
                        if [[ "$RUN_PORT" != "" ]]; then
                            echo "项目端口: $RUN_PORT"
                        fi
                        echo "项目名称: $PROJECT_NAME"
                        echo "项目文件: $CURRENT_DIR/$PARAM_JAR_PATH"
                        echo ""
                        echo " ($WAIT_COUNT) 等待Jar包返回停止状态"
                        echo ""
                        sleep 1s
                        ((WAIT_COUNT++))
                        IS_CURRENT_RUN=$(is_run "$CURRENT_DIR/$CURRENT_DIR_JAR_FILE")
                    done
                    clear
                    echo ""
                    echo "SimpleJarBoot (简单的Jar启动器)"
                    echo ""
                    echo "项目编号: $(get_maven_project_artifact_ids "$CURRENT_DIR/$CURRENT_DIR_JAR_FILE")"
                    echo "项目名称: $PROJECT_NAME"
                    echo "项目文件: $CURRENT_DIR/$PARAM_JAR_PATH"
                    echo ""
                    echo " * Jar已停止 * "
                    echo ""
                else
                    echo "项目编号: $(get_maven_project_artifact_ids "$CURRENT_DIR/$CURRENT_DIR_JAR_FILE")"
                    echo "项目名称: $PROJECT_NAME"
                    echo "项目文件: $CURRENT_DIR/$PARAM_JAR_PATH"
                    echo ""
                    echo " * Jar没有启动 * "
                    echo ""
                fi
            fi
        fi
    done
    if [[ "$JAR_COUNT" == "0" ]]; then
        clear
        echo ""
        echo "SimpleJarBoot (简单的Jar启动器)"
        echo ""
        echo "没有找到要停止的Jar文件"
        echo ""
    fi
}

# 重启
restart() {
    PARAM_JAR_PATH="$1"
    echo ""
    echo "SimpleJarBoot (简单的Jar启动器)"
    echo ""
    clear
    stop $PARAM_JAR_PATH
    start $PARAM_JAR_PATH
}

# 安装Jar包
install() {
    clear
    echo ""
    echo "SimpleJarBoot (简单的Jar启动器)"
    echo ""
    read -r -p "全局安装命令到/usr/bin? [Y/n]" response
    response=${response,,} # tolower
    if [[ $response =~ ^(yes|y| ) ]] || [[ -z $response ]]; then
        clear
        echo ""
        echo "SimpleJarBoot (简单的Jar启动器)"
        echo ""
        # 检查目录是否存在
        if [ -d "/usr/bin" ]; then
            mv $SCRIPT_NAME /usr/bin/simple-jar-boot
            chmod +x /usr/bin/simple-jar-boot
            clear
            echo ""
            echo "SimpleJarBoot (简单的Jar启动器)"
            echo ""
            echo "全局安装完成 simple-jar-boot"
            echo "你可以使用以下命令使用"
            echo ""
            echo "simple-jar-boot"
        else
            echo "/usr/bin 目录不存在 无法安装"
        fi
    else
        clear
        echo ""
        echo "SimpleJarBoot (简单的Jar启动器)"
        echo ""
        echo "没有全局安装 simple-jar-boot"
        echo "你可以使用以下命令使用"
        echo ""
        echo "./$SCRIPT_NAME"
    fi
    echo ""
}

# 卸载
uninstall() {
    clear
    echo ""
    echo "SimpleJarBoot (简单的Jar启动器)"
    echo ""
    echo "$SCRIPT_DIR/$SCRIPT_NAME"
    echo ""
    read -r -p "将会删除以上文件, 是否继续? [Y/n]" response
    response=${response,,} # tolower
    if [[ $response =~ ^(yes|y| ) ]] || [[ -z $response ]]; then
        clear
        echo ""
        echo "SimpleJarBoot (简单的Jar启动器)"
        echo ""
        echo "rm $SCRIPT_DIR/$SCRIPT_NAME"
        echo ""
        if [[ "$SCRIPT_DIR/$SCRIPT_NAME" != "/" ]]; then
            rm -rf "$SCRIPT_DIR/$SCRIPT_NAME"
            echo "卸载成功"
        else
            echo "卸载失败路径有误"
        fi
    else
        clear
        echo ""
        echo "SimpleJarBoot (简单的Jar启动器)"
        echo ""
        echo "已取消卸载"
    fi
    echo ""
}

# 帮助文档
help() {
    clear
    echo ""
    echo "SimpleJarBoot (简单的Jar启动器)"
    echo ""
    echo "使用如下命令进行操作"
    echo ""
    echo "status xxx 查看Jar包运行状态"
    echo "start xxx 启动当前Jar包"
    echo "stop xxx 停止Jar包"
    echo "restart xxx 重启Jar包"
    echo "uninstall 卸载工具"
    if [[ "$SCRIPT_DIR" != "/usr/bin" ]]; then
        echo "install 安装Jar包"
    fi
    echo "(开发中) watch xxx 守护Jar包运行"
    echo ""
    echo "使用如下参数进行补充"
    echo ""
    echo "--config-jar=\"xxx\" Jar包运行配置参数"
    echo "--config-log-path=xxx Jar包日志目录"
    echo "--config-java=xxx 指定运行的Java"
    echo ""
    echo "注意：xxx为Jar对应的文件，若不传参数默认对全部Jar执行操作"
    echo "问题反馈：https://gitee.com/wl4837/simple-jar-boot/issues"
    echo ""
}

# 参数选项
case "$MAIN_PARAM" in
    "status")
     status $FILE_PARAM
     ;;
    "start")
     start $FILE_PARAM
     ;;
    "stop")
     stop $FILE_PARAM
     ;;
    "restart")
     restart $FILE_PARAM
     ;;
    "log")
     log $FILE_PARAM
     ;;
    "uninstall")
     uninstall
     ;;
    "install")
     if [[ "$SCRIPT_DIR" != "/usr/bin" ]]; then
        install
     else
        help
     fi
     ;;
    *)
     help
     ;;
esac
